#include <prism/frontend/semantic_analysis/decorate.hpp>
//=====================================================================
#include <sstream>
//=====================================================================
#include <boost/lexical_cast.hpp>
//=====================================================================
#include <atma/assert.hpp>
//=====================================================================
#include <prism/frontend/syntactical_analysis/parse.hpp>
#include <prism/frontend/syntactical_analysis/marshall.hpp>
//=====================================================================
using namespace atma;
//using namespace sooty;
//=====================================================================

std::string prism::decorate_function(sooty::const_parseme_ptr_ref node)
{
	// special logic for main()
	if ( prism::marshall::function::name(node)->value.string == "main" )
		return "main";
		
	// fucntions are preceded by "F"
	std::stringstream decorated_name;
	decorated_name << "F";
	
	// name
	sooty::const_parseme_ptr_ref name = prism::marshall::function::name(node);
	decorated_name
		<< name->value.string.size()
		<< name->value.string;
	
	// return value
	decorated_name << decorate_type(prism::marshall::function::return_type(node));
	
	// parameters
	sooty::const_parseme_ptr_ref pl = marshall::function::parameter_list(node);
	for (sooty::parseme_container::iterator i = pl->children.begin(); i != pl->children.end(); ++i)
	{
		decorated_name << decorate_type(prism::marshall::variable_definition::type(*i));
	}
	
	return decorated_name.str();
}

struct string_builder
{
	string_builder() {}
	
	template <typename T>
	string_builder(T input) {
		SS << input;
	}
	
	template <typename T>
	string_builder& operator () (T rhs) {
		SS << rhs;
		return *this;
	}
	
	operator std::string() {
		return SS.str();
	}
	
private:
	std::stringstream SS;
};

std::string prism::decorate_type(sooty::const_parseme_ptr_ref n)
{
	using namespace prism;
	
	if (n->id == ID::pointer_type) {
		return "P" + prism::decorate_type(n->children[0]);
	}
	else if (n->id == ID::int_type) {
		return "Ti";
	}
	else if (n->id == ID::real_type) {
		return "Tr";
	}
	else if (n->id == ID::bool_type) {
		return "Tb";
	}
	else if (n->id == ID::void_type) {
		return "Tv";
	}
	else // if (n->id == ID::identifier)
	{
		return string_builder("T")(n->value.string.size())(n->value.string);
	}
}

/*
std::string prism::undecorated_type(sooty::const_parseme_ptr_ref n)
{
	ATMA_ASSERT
		(
			n->id == ID::identifier
			|| n->id == ID::int_type
			|| n->id == ID::resul
		);
		
	if (n->id == ID::identifier)
		return "int";
	else // if (n->id == ID::identifier)
		return n->value.string;
}
*/